package com.ruoyi.business.service.impl;

import cn.hutool.core.date.DateTime;
import com.ruoyi.business.domain.PushInfo;
import com.ruoyi.business.domain.SmsPushRecordDetails;
import com.ruoyi.business.mapper.PushInfoMapper;
import com.ruoyi.business.mapper.SmsPushRecordDetailsMapper;
import com.ruoyi.business.service.IPushService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.QueueConstant;
import com.ruoyi.common.core.domain.dto.PushMessageDTO;
import com.ruoyi.common.core.domain.event.PushMessageEvent;
import com.ruoyi.common.utils.redis.QueueUtils;
import com.ruoyi.sms.domain.bo.DwSmsBO;
import com.ruoyi.sms.domain.dto.DewinSendSmsResponse;
import com.ruoyi.sms.service.Dh3tSendSmsServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.Map;

/**
 * 推送服务 服务层
 * <p>
 * 推送实现:
 * 1. 广播记录推送配置及信息(异步)(生产者)
 * 2. 延迟队列推送(异步)(生产者)
 * 3. 接收消息(redis-queue)并推送消息(每个通道一种消费方式)(消费者)
 * 4. 写表记录推送结果(消费者)
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class PushServiceImpl implements IPushService {

    private final Dh3tSendSmsServiceImpl dh3tSendSmsService;
    private final PushInfoMapper pushInfoMapper;

    /**
     * 记录推送配置
     *
     * @param event 推送事件
     */
    @Async
    @EventListener
    public void push(PushMessageEvent event) {
        log.info("记录推送配置:{}", event);

        // 解析push-to推送到不同队列里去
        Map<String, String> pushMap = event.getPushTo();
        if (pushMap == null || pushMap.isEmpty()) {
            log.error("推送配置为空:{}", event);
            return;
        }

        pushMap.forEach((channel, pushTo) -> {
            PushMessageDTO pushMessageDTO = new PushMessageDTO();
            pushMessageDTO.setPushRef(event.getPushRef());
            pushMessageDTO.setPushTo(pushTo);
            pushMessageDTO.setPushContent(event.getPushContent());
            QueueUtils.addDelayedQueueObject(
                channel,
                pushMessageDTO,
                Math.max(event.getPushTime().getTime() - System.currentTimeMillis(), 0)
            );
        });
    }

    /**
     * 短信队列监听
     */
    @PostConstruct
    public void subscribeSmsQueue() {

        String pushSmsQueue = QueueConstant.PUSH_SMS_QUEUE;
        // QueueUtils.destroyDelayedQueue(pushSmsQueue);
        log.info("通道: {} 监听中......", pushSmsQueue);
        // 项目初始化设置一次即可
        QueueUtils.subscribeBlockingQueue(pushSmsQueue, (PushMessageDTO pushMessageDTO) -> {
            // 观察接收时间
            log.info("通道: {}, 收到数据: {}", pushSmsQueue, pushMessageDTO);

            DwSmsBO dwSmsBO = new DwSmsBO();
            dwSmsBO.setPhones(pushMessageDTO.getPushTo());
            dwSmsBO.setSms(pushMessageDTO.getPushContent());
            dwSmsBO.setBatch(null);
            DewinSendSmsResponse sendSmsResponse = dh3tSendSmsService.sendSms(dwSmsBO);
            log.info("信息发送状态：{}", sendSmsResponse);

            PushInfo pushInfo = new PushInfo();
            pushInfo.setPushRef(pushMessageDTO.getPushRef());
            pushInfo.setPushContent(pushMessageDTO.getPushContent());
            pushInfo.setPushTo(pushMessageDTO.getPushTo());
            pushInfo.setPushType(pushSmsQueue);
            pushInfo.setPushTime(new Date());
            pushInfo.setIsSuccessful(sendSmsResponse.sendSuccess() ? Constants.SUCCESS : Constants.FAIL);
            int insert = pushInfoMapper.insert(pushInfo);
            if (insert <= 0) {
                log.error("记录推送配置失败:{}", pushInfo);
            }
            // 发送记录
            smsPushRecordDetailsMapper.insertSmsSendRecord(dwSmsBO, sendSmsResponse);

        }, true);
    }

    private final SmsPushRecordDetailsMapper smsPushRecordDetailsMapper;

}
